<script lang="ts">
import Spacer from "$lib/Layout/Spacer.svelte";
import AWC from "./../../../../lib/User/BadgeWall/AWC.svelte";
import { user, type User } from "$lib/Data/AniList/user";
import type { Badge } from "../../../../graphql/$types";
import { onDestroy, onMount } from "svelte";
import HeadTitle from "$lib/Home/HeadTitle.svelte";
import {
	databaseTimeToDate,
	dateToInputTime,
	inputTimeToDatabaseTime,
} from "$lib/Utility/time";
import proxy from "$lib/Utility/proxy";
import locale from "$stores/locale";
import Skeleton from "$lib/Loading/Skeleton.svelte";
import Message from "$lib/Loading/Message.svelte";
import Dropdown from "$lib/Layout/Dropdown.svelte";
import { activityText } from "$lib/Data/AniList/activity";
import SettingHint from "$lib/Settings/SettingHint.svelte";
import Popup from "$lib/Layout/Popup.svelte";
import { page } from "$app/stores";
import { browser } from "$app/environment";
import BadgePreview from "$lib/User/BadgeWall/BadgePreview.svelte";
import authorisedJson from "$lib/Data/Static/authorised.json";
import identity from "$stores/identity";
import "$lib/User/BadgeWall/badges.css";
import Badges from "$lib/User/BadgeWall/Badges.svelte";
import type { IndexedBadge } from "$lib/User/BadgeWall/badge";
import { graphql } from "$houdini";
import type { Preferences } from "../../../../graphql/$types";
import localforage from "localforage";
import type { PageData } from "./$types";

export let data: PageData;

$: ({ BadgeWallUser } = data);
$: preferences = $BadgeWallUser.fetching
	? undefined
	: ($BadgeWallUser.data?.User?.preferences as Preferences | undefined);

$: if (browser && preferences && preferences.badge_wall_css) {
	const sanitise = (css: string) =>
		css
			.replace(/\/\*[\s\S]*?\*\//g, "")
			.replace(/<\/?[^>]+(>|$)/g, "")
			.replace(
				/(expression|javascript|vbscript|onerror|onload|onclick|onmouseover|onmouseout|onmouseup|onmousedown|onkeydown|onkeyup|onkeypress|onblur|onfocus|onsubmit|onreset|onselect|onchange|ondblclick):/gi,
				"",
			)
			.replace(/(behaviour|behavior|moz-binding|content):/gi, "")
			.replace(/\s+/g, " ")
			.trim();
	const style = document.createElement("style");

	style.dataset.badgeWall = "true";
	style.innerHTML = sanitise(preferences.badge_wall_css);

	document.head.appendChild(style);
}

const updateBadgeQuery = graphql(`
    mutation UpdateBadge(
      $id: Int
      $post: String
      $image: String
      $description: String
      $time: String
      $category: String
      $hidden: Boolean
      $source: String
      $designer: String
    ) {
      updateBadge(
        id: $id
        post: $post
        image: $image
        description: $description
        time: $time
        category: $category
        hidden: $hidden
        source: $source
        designer: $designer
      ) {
        id

        badges {
          post
          image
          description
          id
          time
          category
          hidden
          source
          designer
          shadow_hidden
          click_count
        }
      }
    }
  `);

const pruneBadgesQuery = graphql(`
    mutation PruneUserBadges {
      pruneUserBadges {
        id

        badges {
          post
          image
          description
          id
          time
          category
          hidden
          source
          designer
          shadow_hidden
          click_count
        }
      }
    }
  `);

const hideCategoryQuery = graphql(`
    mutation HideCategory($category: String) {
      hideBadge(category: $category) {
        id

        badges {
          post
          image
          description
          id
          time
          category
          hidden
          source
          designer
          shadow_hidden
          click_count
        }
      }
    }
  `);

const deleteBadgeQuery = graphql(`
    mutation DeleteBadge($id: Int!) {
      deleteBadge(id: $id) {
        id

        badges {
          post
          image
          description
          id
          time
          category
          hidden
          source
          designer
          shadow_hidden
          click_count
        }
      }
    }
  `);

const shadowHideBadgeQuery = graphql(`
    mutation ShadowHideBadge($id: Int!, $state: Boolean) {
      shadowHideBadge(id: $id, state: $state) {
        id

        badges {
          id
        }
      }
    }
  `);

interface ImportImage {
	link?: string;
	image: string;
}

let editMode = false;
let importMode = false;
let error: null | string;
let awcPromise: Promise<Response>;
let confirmDelete = 0;
let confirmPrune = 0;
let selectedBadge: IndexedBadge | undefined = undefined;
let loadError: string | null = null;
const isId = /^\d+$/.test(data.username);
let importImages: ImportImage[] | undefined = undefined;
let importLinks = false;
let importCategory = "";
let importReplies = false;
let badger: Partial<User> | null;
let migrateMode = false;
let hideMode = false;
const authorised = authorisedJson.includes($identity.id);
let noticeDismissed = false;

$: categoryFilter = new URLSearchParams($page.url.searchParams).get("category");
$: loadQueryParameter = new URLSearchParams($page.url.searchParams).get("load");

type GroupedBadges = { [key: string]: IndexedBadge[] };

const setShadowHide = () => {
	if (!badger) {
		loadError = "Something went wrong. Try refreshing.";

		return;
	}

	shadowHideBadgeQuery.mutate({
		id: badger.id as number,
	});
};

onMount(async () => {
	if (browser && (await localforage.getItem("badgeWallNoticeDismissed")))
		noticeDismissed = true;

	badger = isId
		? {
				id: parseInt(data.username),
				name: "User",
			}
		: await user(data.username);

	if (!badger) {
		loadError = "Couldn't find this user.";

		return;
	}

	awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`));
});

onDestroy(() => {
	if (browser)
		Array.from(document.head.querySelectorAll("style")).forEach((style) => {
			if (style.dataset.badgeWall) style.remove();
		});
});

const submitBadge = () => {
	const imageURL = document.querySelector(
		'input[name="image_url"]',
	) as HTMLInputElement;
	const activityURL = document.querySelector(
		'input[name="activity_url"]',
	) as HTMLInputElement;
	const description = document.querySelector(
		'input[name="description"]',
	) as HTMLInputElement;
	const time = document.querySelector(
		'input[type="datetime-local"]',
	) as HTMLInputElement;
	const category = document.querySelector(
		'input[name="category"]',
	) as HTMLInputElement;
	const hidden = document.querySelector(
		'input[name="hidden"]',
	) as HTMLInputElement;
	const source = document.querySelector(
		'input[name="source"]',
	) as HTMLInputElement;
	const designer = document.querySelector(
		'input[name="designer"]',
	) as HTMLInputElement;

	if (!imageURL.value) {
		error = "Image URL cannot be empty.";

		return;
	}

	if (
		!imageURL.value.startsWith("http") ||
		(activityURL.value.length > 0 && !activityURL.value.startsWith("http"))
	) {
		error = "URLs must start with http or https.";

		return;
	}

	updateBadgeQuery
		.mutate({
			id: selectedBadge?.id,
			image: imageURL.value,
			post: activityURL.value || "#",
			description: description.value,
			category: category.value,
			time: time.value
				? inputTimeToDatabaseTime(new Date(time.value))
				: undefined,
			hidden: hidden.value === "Hidden",
			source: source.value,
			designer: designer.value,
		})
		.then(() => {
			error = null;
			imageURL.value = "";
			activityURL.value = "";
			description.value = "";
			category.value = "";
			hidden.value = "Shown";
			selectedBadge = undefined;
			source.value = "";
			designer.value = "";
		});
};

const removeAllBadges = () => {
	if (confirmPrune === 2) {
		confirmPrune = 0;
	} else if (confirmPrune === 0) {
		confirmPrune = 1;

		return;
	} else {
		confirmPrune = 2;

		return;
	}

	selectedBadge = undefined;

	pruneBadgesQuery.mutate(null).then();
};

const removeBadge = (badge: Badge) => {
	if (!badge.id) return;

	if (confirmDelete === badge.id * 2) {
		confirmDelete = 0;
	} else if (confirmDelete / 4 === badge.id) {
		confirmDelete = badge.id * 2;

		return;
	} else {
		confirmDelete = badge.id * 2;

		return;
	}

	selectedBadge = undefined;

	deleteBadgeQuery
		.mutate({
			id: badge.id,
		})
		.then();
};

const groupBadges = (badges: IndexedBadge[]) => {
	const groupedBadges: GroupedBadges = {};

	badges.forEach((badge) => {
		if (!badge.category) badge.category = "Uncategorised";

		if (!groupedBadges[badge.category]) groupedBadges[badge.category] = [];

		groupedBadges[badge.category].push(badge);
	});

	Object.entries(groupedBadges).forEach(([_categoryKey, badges]) => {
		badges.forEach((badge, index) => {
			badge.index = index;
		});
	});

	return Object.entries(groupedBadges)
		.sort((a, b) => a[1].length - b[1].length)
		.sort((a, b) => {
			const pinnedCategories =
				preferences && preferences.pinned_badge_wall_categories
					? preferences.pinned_badge_wall_categories
					: ([] as string[]);
			const aIndex = pinnedCategories.indexOf(a[0]);
			const bIndex = pinnedCategories.indexOf(b[0]);

			if (aIndex === -1 && bIndex === -1) return 0;
			if (aIndex === -1) return 1;
			if (bIndex === -1) return -1;

			return aIndex - bIndex;
		})
		.reduce((set: GroupedBadges, [key, value]) => {
			set[key] = value;

			return set;
		}, {});
};

const parsePost = async () => {
	if (importImages && importImages.length > 0) importImages = undefined;

	const link = (
		document.querySelector("#import_activity_url") as HTMLInputElement
	).value;
	const type = link.replace(/.*\/(activity|thread)\/(\d+).*/, "$1");
	const id = link.replace(/.*\/(activity|thread)\/(\d+).*/, "$2");

	if (type !== "activity") return null;

	let text = await activityText(parseInt(id), importReplies);

	const images: ImportImage[] = [];

	if (importLinks) {
		Array.from(
			new DOMParser().parseFromString(text, "text/html").querySelectorAll("a"),
		).forEach((a) => {
			const anchor = a as HTMLAnchorElement;

			if (anchor.querySelector("img")) {
				images.push({
					link: anchor.href,
					image: (anchor.querySelector("img") as HTMLImageElement).src,
				});
			}
		});

		text = text.replace(/<a.*?>.*?<img.*?>.*?<\/a>/g, "");

		Array.from(
			new DOMParser()
				.parseFromString(text, "text/html")
				.querySelectorAll("img"),
		).forEach((img) => {
			const image = img as HTMLImageElement;

			images.push({
				image: image.src,
			});
		});
	} else {
		Array.from(
			new DOMParser()
				.parseFromString(text, "text/html")
				.querySelectorAll("img"),
		).forEach((img) => {
			const image = img as HTMLImageElement;

			images.push({
				image: image.src,
			});
		});
	}

	importImages = images;
};

const importBadges = () =>
	fetch(
		`/api/badges?import=true
			${importCategory.length > 0 ? `&category=${encodeURIComponent(importCategory)}` : ""}
		`,
		{
			method: "PUT",
			headers: {
				"Content-Type": "application/json",
			},
			body: JSON.stringify(
				importImages?.map((image) => ({
					image: image.image,
					post: image.link || "#",
					category: importCategory,
				})),
			),
		},
	).then(() => {
		importMode = false;
		importImages = undefined;
	});

const migrateCategory = () => {
	fetch(
		`/api/badges?migrate=true&original=${encodeURIComponent(
			(document.querySelector("#migrate_original") as HTMLInputElement).value,
		)}&new=${encodeURIComponent(
			(document.querySelector("#migrate_new") as HTMLInputElement).value,
		)}`,
		{
			method: "PUT",
		},
	).then(() => (migrateMode = false));
};

const hideCategory = () => {
	hideCategoryQuery
		.mutate({
			category: (document.querySelector("#category_hide") as HTMLInputElement)
				.value,
		})
		.then(() => (hideMode = false));
};

const removeHiddenBadges = (isOwner: boolean, badges: IndexedBadge[]) =>
	isOwner || authorised
		? badges
		: badges.filter((b) => !b.hidden && !b.shadow_hidden);

const setAdjacentCursor = (badges: IndexedBadge[], direction: number) => {
	const currentCategory = selectedBadge?.category || "Uncategorised";
	const currentBadge = selectedBadge?.index;
	const categoryBadges = groupBadges(badges)[currentCategory];

	if (!currentCategory || currentBadge === undefined) return;

	let previousBadge = categoryBadges[currentBadge + direction];

	while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden))
		previousBadge = categoryBadges[previousBadge.index + direction];

	if (previousBadge) selectedBadge = previousBadge;
};

const adjacentBadgeExists = (
	selectedBadge: IndexedBadge | undefined,
	badges: IndexedBadge[],
	direction: number,
) => {
	const currentCategory = selectedBadge?.category || "Uncategorised";
	const currentBadge = selectedBadge?.index;
	const categoryBadges = groupBadges(badges)[currentCategory];

	if (!currentCategory || currentBadge === undefined || !categoryBadges) return;

	let previousBadge = categoryBadges[currentBadge + direction];

	while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden))
		previousBadge = categoryBadges[previousBadge.index + direction];

	return previousBadge;
};

const castAsStringArray = (array: unknown[]) => array as string[];

const castBadgesToIndexedBadges = (array: unknown[]) => array as IndexedBadge[];

const shadowHideBadge = () => {
	if (!selectedBadge && !authorised) return;

	if (!badger) {
		loadError = "Something went wrong. Try refreshing.";

		return;
	}

	shadowHideBadgeQuery
		.mutate({
			id: badger.id as number,
			state: selectedBadge?.shadow_hidden as boolean,
		})
		.then();
};
</script>

<HeadTitle route={`${data.username}'s Badge Wall`} path={`/user/${data.username}`} />

{#if loadError}
  <Popup fullscreen locked>
    {loadError}
  </Popup>
{:else}
  {@const isOwner = $identity && (isId ? $identity.id : $identity.name) === data.username}

  {#if $BadgeWallUser.fetching || !$BadgeWallUser.data}
    <Message message="Loading badges ..." />

    <Skeleton grid={true} count={100} width="150px" height="170px" />
  {:else if !$BadgeWallUser.data.User}
    <Message message="No badges yet." />
  {:else}
    {@const ungroupedBadges = castBadgesToIndexedBadges($BadgeWallUser.data.User.badges)}
    {@const isBadgeSelected =
      selectedBadge &&
      selectedBadge !== undefined &&
      selectedBadge.image &&
      selectedBadge.image !== undefined &&
      !editMode}

    <div id="badges">
      {#if preferences && !preferences.hide_awc_badges}
        <AWC {awcPromise} {categoryFilter} {isOwner} {preferences} />
      {/if}

      {#if ungroupedBadges === null}
        <Message message="Loading badges ..." />

        <Skeleton grid={true} count={10} width="150px" height="170px" />
      {:else}
        {@const groupedBadges = Object.entries(
          groupBadges(removeHiddenBadges(isOwner, ungroupedBadges))
        )}

        {#if isOwner || authorised}
          {@const shadowHiddenCount = ungroupedBadges.filter((badge) => badge.shadow_hidden).length}
          {@const shadowHidden = shadowHiddenCount > 0}

          {#if shadowHidden}
            <div class="card">
              <b>Notice:</b> The Badge Wall overseer system has detected badges containing
              AI-generated material on your wall. {shadowHiddenCount} of your badges have been shadow
              hidden.
              <Spacer />
              You may use the "Un-shadow Hide Badges" button to unhide these badges, from where you will
              be required to use the hide feature to hide these badges from the public, while allowing
              them to stay visible to you as the account holder.
            </div>
          {:else if !noticeDismissed}
            <div class="card">
              <b>Notice:</b> AniList has begun purging outbound links which contain AI-generated
              material, this includes Badge Wall. If you have collected badges with AI-generated
              elements, kindly use the hide feature to hide these badges from the public, while
              allowing them to stay visible to you as the account holder.
              <Spacer />
              Failure to comply with this request at your earliest convenience will result in the hiding
              of all badges from your Badge Wall.
              <Spacer />
              <button
                onclick={async () => {
                  noticeDismissed = true;

                  await localforage.setItem('badgeWallNoticeDismissed', 'true');
                }}
              >
                Dismiss
              </button>
            </div>
          {/if}

          <Spacer />

          <div class="card">
            {#if authorised}
              <button onclick={setShadowHide}>Shadow Hide Badges</button>
            {/if}

            {#if isOwner && authorised}
              <span style="margin: 0 0.625rem;">•</span>
            {/if}

            {#if isOwner}
              <button
                onclick={() => {
                  selectedBadge = undefined;
                  editMode = !editMode;
                }}
              >
                {editMode
                  ? $locale().user.badges.editMode.disable
                  : $locale().user.badges.editMode.enable}
              </button>
              <span style="margin: 0 0.625rem;">•</span>
              <button
                onclick={() => {
                  selectedBadge = undefined;
                  importMode = !importMode;
                }}
              >
                {importMode
                  ? $locale().user.badges.importMode.disable
                  : $locale().user.badges.importMode.enable}
              </button>
              <span style="margin: 0 0.625rem;">•</span>
              <button
                onclick={() => {
                  selectedBadge = undefined;
                  migrateMode = !migrateMode;
                }}
              >
                Migrate Category
              </button>
              <span style="margin: 0 0.625rem;">•</span>
              <button
                onclick={() => {
                  selectedBadge = undefined;
                  hideMode = !hideMode;
                }}
              >
                Hide Category
              </button>
              <!-- <!-- <span style="margin: 0 0.625rem;">•</span> -->
              <!-- <button onclick={() => exportBadges(groupedBadges)}>Export Badges</button> -->

              {#if shadowHidden}
                <span style="margin: 0 0.625rem;">•</span>
                <button onclick={setShadowHide}>Un-shadow Hide Badges</button>
              {/if}

              {#if editMode && isOwner}
                {@const groups = groupedBadges
                  .map((group) => group[0])
                  .filter((group) => group !== 'Uncategorised')}
                {@const designers = castAsStringArray([
                  ...new Set(
                    ungroupedBadges
                      .map((badge) => badge.designer)
                      .filter((designer) => designer !== undefined && designer !== null)
                      .filter(
                        (designer, index, array) =>
                          array.indexOf(designer) === index && !array.includes(`@${designer}`)
                      )
                  )
                ])}

                <Spacer />

                {#if error}
                  <p style="color: red;">{error}</p>
                {/if}

                <input
                  type="text"
                  placeholder={$locale().user.badges.editMode.imageURL}
                  name="image_url"
                  minlength="1"
                  maxlength="1000"
                  size="15"
                  value={selectedBadge ? selectedBadge.image : ''}
                />
                <input
                  type="text"
                  placeholder={$locale().user.badges.editMode.activityURL}
                  name="activity_url"
                  minlength="1"
                  maxlength="1000"
                  size="15"
                  value={selectedBadge
                    ? selectedBadge.post === '#'
                      ? ''
                      : selectedBadge.post
                    : ''}
                />
                <input
                  type="text"
                  placeholder={$locale().user.badges.editMode.description}
                  name="description"
                  minlength="1"
                  maxlength="1000"
                  size="15"
                  value={selectedBadge ? selectedBadge.description : ''}
                />
                <Dropdown
                  items={groups.map((group) => ({
                    name: group,
                    url: '#',
                    onClick: () => {
                      const category = document.querySelector('input[name="category"]');

                      if (category instanceof HTMLInputElement) category.value = group;
                    }
                  }))}
                  header={false}
                  center={false}
                >
                  <span slot="title">
                    <input
                      type="text"
                      placeholder={$locale().user.badges.editMode.category}
                      name="category"
                      minlength="1"
                      maxlength="1000"
                      size="15"
                      value={selectedBadge
                        ? selectedBadge.category === 'Uncategorised'
                          ? ''
                          : selectedBadge.category
                        : ''}
                      list="categories"
                    />
                  </span>
                </Dropdown>
                <span style="float: right;">
                  <input
                    type="datetime-local"
                    value={selectedBadge && selectedBadge.time
                      ? dateToInputTime(databaseTimeToDate(selectedBadge.time))
                      : ''}
                  />
                  <small>Must be full date and time, defaults to now if any fields empty</small>
                </span>

                <Spacer />

                <div class="edit-row-2">
                  <input
                    type="text"
                    placeholder={$locale().user.badges.editMode.source}
                    name="source"
                    minlength="1"
                    maxlength="1000"
                    size="16"
                    value={selectedBadge ? selectedBadge.source : ''}
                  />
                  <Dropdown
                    items={designers.map((designer) => ({
                      name: designer,
                      url: '#',
                      onClick: () => {
                        const designerField = document.querySelector('input[name="designer"]');

                        if (designerField instanceof HTMLInputElement)
                          designerField.value = designer;
                      }
                    }))}
                    header={false}
                    center={false}
                  >
                    <span slot="title">
                      <input
                        type="text"
                        placeholder={$locale().user.badges.editMode.designer}
                        name="designer"
                        minlength="1"
                        maxlength="1000"
                        size="17"
                        value={selectedBadge ? selectedBadge.designer : ''}
                      />
                    </span>
                  </Dropdown>
                  <Dropdown
                    items={[false, true].map((hidden) => ({
                      name: hidden ? 'Hidden' : 'Shown',
                      url: '#',
                      onClick: () => {
                        const hiddenInput = document.querySelector('input[name="hidden"]');

                        if (hiddenInput instanceof HTMLInputElement)
                          hiddenInput.value = hidden ? 'Hidden' : 'Shown';
                      }
                    }))}
                    header={false}
                    center={false}
                  >
                    <span slot="title">
                      <input
                        type="text"
                        placeholder="Shown"
                        name="hidden"
                        minlength="1"
                        maxlength="1000"
                        size="15"
                        value={selectedBadge
                          ? selectedBadge.hidden
                            ? 'Hidden'
                            : 'Shown'
                          : 'Shown'}
                      />
                    </span>
                  </Dropdown>
                  <button class="button-lined" onclick={submitBadge}
                    >{selectedBadge
                      ? $locale().user.badges.editMode.update
                      : $locale().user.badges.editMode.add}</button
                  >
                  {#if selectedBadge}
                    {$locale().user.badges.editMode.or}
                    <button
                      class="button-lined"
                      onclick={() => {
                        if (selectedBadge) removeBadge(selectedBadge);
                      }}>{$locale().user.badges.editMode.delete}</button
                    >
                  {/if}
                </div>
              {/if}
            {/if}
          </div>
        {/if}

        <Spacer />

        {#if loadQueryParameter === 'none'}
          <div class="card">
            <b>Notice:</b>
            {ungroupedBadges.length} badges have been loaded successfully, but they are not being displayed
            due to your preferences (<code>load=none</code>).
          </div>
        {:else}
          <Badges
            {ungroupedBadges}
            {groupedBadges}
            {categoryFilter}
            {editMode}
            {preferences}
            bind:selectedBadge
          />
        {/if}
      {/if}
    </div>

    {#if isBadgeSelected}
      <!-- {@const anyAdjacentBadgeExists =
							adjacentBadgeExists(selectedBadge, ungroupedBadges, -1) ||
							adjacentBadgeExists(selectedBadge, ungroupedBadges, 1)} -->

      <Popup
        fullscreen
        show={isBadgeSelected}
        onLeave={() => {
          selectedBadge = undefined;
        }}
      >
        <BadgePreview
          bind:selectedBadge
          onNext={() => setAdjacentCursor(ungroupedBadges, 1)}
          onPrevious={() => setAdjacentCursor(ungroupedBadges, -1)}
          hasNext={adjacentBadgeExists(selectedBadge, ungroupedBadges, 1) !== undefined}
          hasPrevious={adjacentBadgeExists(selectedBadge, ungroupedBadges, -1) !== undefined}
        />

        {#if authorised}
          <button onclick={shadowHideBadge}>
            {#if selectedBadge && selectedBadge.shadow_hidden}
              Un-shadow
            {:else}
              Shadow
            {/if} Hide Badge ({selectedBadge ? selectedBadge.id : 0})
          </button>
        {/if}
      </Popup>
    {/if}
  {/if}
{/if}

{#if true}
  <Popup fullscreen onLeave={() => (importMode = false)} show={importMode}>
    {$locale().user.badges.importMode.title}

    <Spacer />

    <input
      type="text"
      placeholder={$locale().user.badges.editMode.activityURL}
      id="import_activity_url"
      minlength="1"
      maxlength="1000"
      size="20"
    />
    <input
      type="text"
      placeholder={$locale().user.badges.editMode.category}
      id="import_category"
      minlength="1"
      maxlength="1000"
      size="20"
    />

    <Spacer />

    <input type="checkbox" id="import_links" name="import_links" bind:checked={importLinks} />
    {$locale().user.badges.importMode.importLinks.title}
    <SettingHint lineBreak>
      {$locale().user.badges.importMode.importLinks.hint}
    </SettingHint>

    <Spacer />

    <input type="checkbox" id="import_links" name="import_links" bind:checked={importReplies} />
    {$locale().user.badges.importMode.importReplies}

    <Spacer />

    <button
      onclick={() => {
        importMode = false;
        importImages = undefined;
      }}
      class="button-lined"
    >
      {$locale().user.badges.importMode.cancel}
    </button>
    <button onclick={() => parsePost()} class="button-lined" style="float: right;">
      {$locale().user.badges.importMode.fetch}
    </button>

    <Spacer />

    <details>
      <summary>{$locale().user.badges.importMode.dangerous}</summary>

      <button
        class="button-lined no-shadow"
        data-umami-event="Remove All Badges"
        onclick={removeAllBadges}
      >
        {$locale({
          values: {
            times: 3 - confirmPrune
          }
        }).user.badges.importMode.deleteAll.title}
      </button>
      <SettingHint lineBreak>
        {$locale().user.badges.importMode.deleteAll.hint}
      </SettingHint>
    </details>

    {#if importImages && importImages.length > 0}
      <Spacer />

      {$locale({
        values: {
          count: importImages.length
        }
      }).user.badges.importMode.importConfirm}&nbsp;
      <button
        onclick={() => importBadges()}
        class="button-lined no-shadow"
        data-umami-event="Import Badges"
      >
        {$locale().user.badges.importMode.import}
      </button>

      <SettingHint lineBreak>
        {$locale().user.badges.importMode.importWait}
      </SettingHint>
    {/if}
  </Popup>
{/if}

<Popup fullscreen onLeave={() => (migrateMode = false)} show={migrateMode}>
  Migrate Category

  <Spacer />

  <input
    type="text"
    placeholder="Original Category"
    id="migrate_original"
    minlength="1"
    maxlength="1000"
    size="20"
  />
  <input
    type="text"
    placeholder="New Category"
    id="migrate_new"
    minlength="1"
    maxlength="1000"
    size="20"
  />
  <SettingHint lineBreak>Leave category empty to migrate all to or from uncategorised.</SettingHint>

  <Spacer />

  <button
    onclick={() => {
      importMode = false;
      importImages = undefined;
    }}
    class="button-lined"
  >
    {$locale().user.badges.importMode.cancel}
  </button>
  <button onclick={() => migrateCategory()} class="button-lined" style="float: right;">
    Migrate
  </button>
</Popup>

<Popup fullscreen onLeave={() => (hideMode = false)} show={hideMode}>
  Hide Category

  <SettingHint lineBreak>
    If the majority of the badges in a category are shown, the category will be hidden, and vice
    versa.
  </SettingHint>

  <Spacer />

  <input
    type="text"
    placeholder="Category"
    id="category_hide"
    minlength="1"
    maxlength="1000"
    size="20"
  />
  <SettingHint lineBreak>Leave category field empty to hide all.</SettingHint>

  <Spacer />

  <button
    onclick={() => {
      hideMode = false;
      importImages = undefined;
    }}
    class="button-lined"
  >
    {$locale().user.badges.importMode.cancel}
  </button>
  <button onclick={() => hideCategory()} class="button-lined" style="float: right;"
    >Toggle Visibility</button
  >
</Popup>
